﻿using Microsoft.Data.Edm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.OData.Routing;
using System.Web.Http.OData.Routing.Conventions;
using WooCoo.Tools;

namespace WooCoo.DataPortal.WebHost.ODataServer
{
    /// <summary>
    /// 为WooCoo OData请求路由转换,所有注册的实体集合的ODataPortal请求都将转至ODataPortalController.
    /// </summary>
    public class EntityListRoutingConvention : IODataRoutingConvention
    {
        /// <summary>选择controller</summary>
        /// <returns>null if the request isn't handled by this convention; otherwise, the name of the selected controller</returns>
        /// <param name="odataPath">The OData path.</param>
        /// <param name="request">The request.</param>
        public string SelectController(ODataPath odataPath, HttpRequestMessage request)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }
            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }
            EntitySetPathSegment entitySetPathSegment = odataPath.Segments.FirstOrDefault<ODataPathSegment>() as EntitySetPathSegment;
            if (entitySetPathSegment != null)
            {
                return "ODataPortal";
            }
            return null;
        }
        /// <summary>Selects the action for OData requests.</summary>
        /// <returns>null if the request isn't handled by this convention; otherwise, the name of the selected action</returns>
        /// <param name="odataPath">The OData path.</param>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="actionMap">The action map.</param>
        public virtual string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null)
            {
                throw Error.ArgumentNull("odataPath");
            }
            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }
            if (actionMap == null)
            {
                throw Error.ArgumentNull("actionMap");
            }

            if (odataPath.PathTemplate == "~/entityset")
            {
                string actionName = null;
                EntitySetPathSegment entitySetPathSegment = odataPath.Segments[0] as EntitySetPathSegment;
                IEdmEntitySet entitySet = entitySetPathSegment.EntitySet;
                HttpMethod method = controllerContext.Request.Method;
                string text;
                switch (method.ToString().ToUpperInvariant())
                {
                    case "GET":
                        text = "Get";
                        break;
                    case "PATCH":
                    case "MERGE":
                        text = "Patch";
                        break;
                    case "DELETE":
                        text = "Delete";
                        break;
                    case "PUT":
                        text = "Put";
                        break;
                    case "POST":
                        text = "Post";
                        break;
                    default:
                        text = null;
                        break;
                }
                actionName = this.FindMatchingAction(actionMap, new string[]
					{
						text + entitySet.ElementType.Name,
						text
					});
                //if (method == HttpMethod.Get)
                //{
                //    actionName = this.FindMatchingAction(actionMap, new string[]
                //    {
                //        "Get" + entitySet.ElementType.Name+"List",
                //        "Get"
                //    });
                //}
                //else if (method == HttpMethod.Post)
                //{
                //    actionName = this.FindMatchingAction(actionMap, new string[]
                //    {
                //        "Post" + entitySet.ElementType.Name,
                //        "Post"
                //    });
                //}
                if(!string.IsNullOrEmpty(actionName))
                {
                    controllerContext.RouteData.Values[ODataServerConstants.ContractNameKey] = entitySet.ElementType.Name;
                }
                return actionName;
            }
            return null;
        }
        public string FindMatchingAction(ILookup<string, HttpActionDescriptor> actionMap, params string[] targetActionNames)
        {
            for (int i = 0; i < targetActionNames.Length; i++)
            {
                string text = targetActionNames[i];
                if (actionMap.Contains(text))
                {
                    return text;
                }
            }
            return null;
        }
    }
}